package com.example.smartpark.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartpark.dto.AnnouncementDTO;
import com.example.smartpark.dto.AnnouncementQueryDTO;
import com.example.smartpark.exception.BusinessException;
import com.example.smartpark.mapper.AnnouncementCategoryMapper;
import com.example.smartpark.mapper.AnnouncementMapper;
import com.example.smartpark.mapper.AnnouncementReadMapper;
import com.example.smartpark.mapper.UserMapper;
import com.example.smartpark.model.Announcement;
import com.example.smartpark.model.AnnouncementCategory;
import com.example.smartpark.model.AnnouncementRead;
import com.example.smartpark.model.User;
import com.example.smartpark.service.AnnouncementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * 公告Service实现类
 */
@Slf4j
@Service
public class AnnouncementServiceImpl extends ServiceImpl<AnnouncementMapper, Announcement> implements AnnouncementService {

    @Autowired
    private AnnouncementCategoryMapper categoryMapper;

    @Autowired
    private AnnouncementReadMapper readMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public IPage<AnnouncementDTO> getAnnouncementPage(AnnouncementQueryDTO queryDTO) {
        // 构建查询条件
        LambdaQueryWrapper<Announcement> queryWrapper = new LambdaQueryWrapper<>();
        
        // 只查询已发布的公告
        queryWrapper.eq(Announcement::getStatus, 1);
        
        // 当前时间在生效时间范围内
        Date now = new Date();
        queryWrapper.le(Announcement::getStartTime, now);
        queryWrapper.ge(Announcement::getEndTime, now);
        
        // 标题模糊查询
        if (StringUtils.hasText(queryDTO.getTitle())) {
            queryWrapper.like(Announcement::getTitle, queryDTO.getTitle());
        }
        
        // 分类查询
        if (queryDTO.getCategoryId() != null) {
            queryWrapper.eq(Announcement::getCategoryId, queryDTO.getCategoryId());
        }
        
        // 是否置顶查询
        if (queryDTO.getIsTop() != null) {
            queryWrapper.eq(Announcement::getIsTop, queryDTO.getIsTop());
        }
        
        // 排序：先按置顶降序，再按优先级降序，最后按创建时间降序
        queryWrapper.orderByDesc(Announcement::getIsTop)
                .orderByDesc(Announcement::getPriority)
                .orderByDesc(Announcement::getCreatedAt);
        
        // 分页查询
        Page<Announcement> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        IPage<Announcement> announcementPage = this.page(page, queryWrapper);
        
        // 转换为DTO
        return announcementPage.convert(this::convertToDTO);
    }

    @Override
    public AnnouncementDTO getAnnouncementById(Long id, Integer userId) {
        // 获取公告
        Announcement announcement = this.getById(id);
        if (announcement == null) {
            throw new BusinessException("公告不存在");
        }
        
        // 如果公告未发布且不是管理员查看，则不允许查看
        if (announcement.getStatus() != 1) {
            User user = userMapper.selectById(userId);
            if (user == null || user.getRole() != 1) {
                throw new BusinessException("公告不存在或未发布");
            }
        }
        
        // 记录阅读状态
        if (userId != null) {
            recordRead(id, userId);
        }
        
        // 更新阅读次数
        announcement.setReadCount(announcement.getReadCount() + 1);
        this.updateById(announcement);
        
        // 转换为DTO
        return convertToDTO(announcement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AnnouncementDTO createAnnouncement(AnnouncementDTO announcementDTO) {
        // 验证分类是否存在
        AnnouncementCategory category = categoryMapper.selectById(announcementDTO.getCategoryId());
        if (category == null) {
            throw new BusinessException("公告分类不存在");
        }
        
        // 设置默认值
        if (announcementDTO.getPriority() == null) {
            announcementDTO.setPriority(0);
        }
        if (announcementDTO.getIsTop() == null) {
            announcementDTO.setIsTop(0);
        }
        if (announcementDTO.getStatus() == null) {
            announcementDTO.setStatus(0); // 默认为草稿状态
        }
        announcementDTO.setReadCount(0);
        
        // 转换为实体
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(announcementDTO, announcement);
        
        // 保存
        this.save(announcement);
        
        // 返回DTO
        return convertToDTO(announcement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AnnouncementDTO updateAnnouncement(Long id, AnnouncementDTO announcementDTO) {
        // 验证公告是否存在
        Announcement announcement = this.getById(id);
        if (announcement == null) {
            throw new BusinessException("公告不存在");
        }
        
        // 验证分类是否存在
        if (announcementDTO.getCategoryId() != null) {
            AnnouncementCategory category = categoryMapper.selectById(announcementDTO.getCategoryId());
            if (category == null) {
                throw new BusinessException("公告分类不存在");
            }
        }
        
        // 更新属性
        if (StringUtils.hasText(announcementDTO.getTitle())) {
            announcement.setTitle(announcementDTO.getTitle());
        }
        if (StringUtils.hasText(announcementDTO.getContent())) {
            announcement.setContent(announcementDTO.getContent());
        }
        if (announcementDTO.getCategoryId() != null) {
            announcement.setCategoryId(announcementDTO.getCategoryId());
        }
        if (announcementDTO.getPriority() != null) {
            announcement.setPriority(announcementDTO.getPriority());
        }
        if (announcementDTO.getStartTime() != null) {
            announcement.setStartTime(announcementDTO.getStartTime());
        }
        if (announcementDTO.getEndTime() != null) {
            announcement.setEndTime(announcementDTO.getEndTime());
        }
        if (announcementDTO.getIsTop() != null) {
            announcement.setIsTop(announcementDTO.getIsTop());
        }
        if (announcementDTO.getStatus() != null) {
            announcement.setStatus(announcementDTO.getStatus());
        }
        
        // 保存
        this.updateById(announcement);
        
        // 返回DTO
        return convertToDTO(announcement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAnnouncement(Long id) {
        // 验证公告是否存在
        Announcement announcement = this.getById(id);
        if (announcement == null) {
            throw new BusinessException("公告不存在");
        }
        
        // 删除公告
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AnnouncementDTO changeAnnouncementStatus(Long id, Integer status) {
        // 验证公告是否存在
        Announcement announcement = this.getById(id);
        if (announcement == null) {
            throw new BusinessException("公告不存在");
        }
        
        // 验证状态值
        if (status < 0 || status > 2) {
            throw new BusinessException("无效的状态值");
        }
        
        // 更新状态
        announcement.setStatus(status);
        this.updateById(announcement);
        
        // 返回DTO
        return convertToDTO(announcement);
    }

    @Override
    public IPage<AnnouncementDTO> getAdminAnnouncementPage(AnnouncementQueryDTO queryDTO) {
        // 构建查询条件
        LambdaQueryWrapper<Announcement> queryWrapper = new LambdaQueryWrapper<>();
        
        // 标题模糊查询
        if (StringUtils.hasText(queryDTO.getTitle())) {
            queryWrapper.like(Announcement::getTitle, queryDTO.getTitle());
        }
        
        // 分类查询
        if (queryDTO.getCategoryId() != null) {
            queryWrapper.eq(Announcement::getCategoryId, queryDTO.getCategoryId());
        }
        
        // 是否置顶查询
        if (queryDTO.getIsTop() != null) {
            queryWrapper.eq(Announcement::getIsTop, queryDTO.getIsTop());
        }
        
        // 状态查询
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq(Announcement::getStatus, queryDTO.getStatus());
        }
        
        // 发布者查询
        if (queryDTO.getPublisherId() != null) {
            queryWrapper.eq(Announcement::getPublisherId, queryDTO.getPublisherId());
        }
        
        // 时间范围查询
        if (queryDTO.getStartTime() != null) {
            queryWrapper.ge(Announcement::getCreatedAt, queryDTO.getStartTime());
        }
        if (queryDTO.getEndTime() != null) {
            queryWrapper.le(Announcement::getCreatedAt, queryDTO.getEndTime());
        }
        
        // 排序：按创建时间降序
        queryWrapper.orderByDesc(Announcement::getCreatedAt);
        
        // 分页查询
        Page<Announcement> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        IPage<Announcement> announcementPage = this.page(page, queryWrapper);
        
        // 转换为DTO
        return announcementPage.convert(this::convertToDTO);
    }

    /**
     * 记录用户阅读状态
     *
     * @param announcementId 公告ID
     * @param userId 用户ID
     */
    private void recordRead(Long announcementId, Integer userId) {
        // 查询是否已有阅读记录
        LambdaQueryWrapper<AnnouncementRead> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AnnouncementRead::getAnnouncementId, announcementId)
                .eq(AnnouncementRead::getUserId, userId);
        AnnouncementRead read = readMapper.selectOne(queryWrapper);
        
        if (read == null) {
            // 创建新的阅读记录
            read = new AnnouncementRead();
            read.setAnnouncementId(announcementId);
            read.setUserId(userId);
            read.setIsRead(1);
            read.setReadTime(new Date());
            readMapper.insert(read);
        } else if (read.getIsRead() == 0) {
            // 更新已有记录为已读
            read.setIsRead(1);
            read.setReadTime(new Date());
            readMapper.updateById(read);
        }
    }

    /**
     * 将实体转换为DTO
     *
     * @param announcement 公告实体
     * @return 公告DTO
     */
    private AnnouncementDTO convertToDTO(Announcement announcement) {
        if (announcement == null) {
            return null;
        }
        
        AnnouncementDTO dto = new AnnouncementDTO();
        BeanUtils.copyProperties(announcement, dto);
        
        // 设置分类名称
        AnnouncementCategory category = categoryMapper.selectById(announcement.getCategoryId());
        if (category != null) {
            dto.setCategoryName(category.getName());
        }
        
        // 设置发布者名称
        User publisher = userMapper.selectById(announcement.getPublisherId());
        if (publisher != null) {
            dto.setPublisherName(publisher.getUsername());
        }
        
        // 设置状态描述
        dto.setStatusDesc(getStatusDesc(announcement.getStatus()));
        
        return dto;
    }

    /**
     * 获取状态描述
     *
     * @param status 状态值
     * @return 状态描述
     */
    private String getStatusDesc(Integer status) {
        switch (status) {
            case 0:
                return "草稿";
            case 1:
                return "已发布";
            case 2:
                return "已下线";
            default:
                return "未知状态";
        }
    }
} 